package cn.topevery.garden.dal.util;

import cn.topevery.garden.entity.dto.flow.RebootFlowPara;
import cn.topevery.garden.entity.dto.flow.SendActPara;
import cn.topevery.garden.framework.config.EventFlowConfig;
import hw.topevery.af.entity.bo.RuntimeActivity;
import hw.topevery.af.entity.enums.HandleEnum;
import hw.topevery.af.entity.enums.LimitTypeEnum;
import hw.topevery.af.entity.enums.ReceiveTypeEnum;
import hw.topevery.af.entity.vo.*;
import hw.topevery.af.runtime.WorkflowDefineManager;
import hw.topevery.af.runtime.WorkflowRuntimeManager;
import hw.topevery.framework.Utility;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author yong.chen
 * @date 2020/9/15
 * @description 流程帮助类
 */

@Component
public class WorkFlowUtil {

    @Autowired
    private WorkflowRuntimeManager workflowRuntimeManager;

    @Autowired
    private WorkflowDefineManager workflowDefineManager;


    /**
     * 开启流程
     *
     * @param workFlowIdentifyId 流程标识id
     * @param inUserId           来件用户id
     * @param inUserName         来件用户名称
     * @param receiveTypeEnum    下一环节接收对象
     * @param receiveId          下一环节接收对象id
     * @param receiveName        下一环节接收对象名称
     * @param limit              下一环节时限
     * @return
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public StartResult startWorkFlow(String workFlowIdentifyId, String inUserId, String inUserName, ReceiveTypeEnum receiveTypeEnum, String receiveId, String receiveName, Integer limit) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        StartPara startPara = new StartPara();
        //region 当前环节信息
        startPara.setDate(LocalDateTime.now());
        startPara.setUserId(inUserId);
        startPara.setUserName(inUserName);
        //FIXME 环节状态
        startPara.setNextActivityStatus(0);
        // endregion

        //region 下一环节信息
        startPara.setLimit(limit);
        startPara.setReceiverType(receiveTypeEnum);
        startPara.setReceiverId(receiveId);
        startPara.setReceiverName(receiveName);
        //endregion
        startPara.setWfIdentifier(workFlowIdentifyId);
        StartResult startResult = workflowRuntimeManager.startActivity(startPara);
        return startResult;
    }

    /**
     * 开启流程
     *
     * @param workFlowIdentifyId 流程标识id
     * @param inUserId           来件用户id
     * @param inUserName         来件用户名称
     * @param receiveTypeEnum    下一环节接收对象
     * @param receiveId          下一环节接收对象id
     * @param receiveName        下一环节接收对象名称
     * @return
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public StartResult startWorkFlow(String workFlowIdentifyId, String inUserId, String inUserName, ReceiveTypeEnum receiveTypeEnum, String receiveId, String receiveName) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        return startWorkFlow(workFlowIdentifyId, inUserId, inUserName, receiveTypeEnum, receiveId, receiveName, 0);
    }

    /**
     * 开启流程
     *
     * @param inUserId        来件用户id
     * @param inUserName      来件用户名称
     * @param receiveTypeEnum 下一环节接收对象
     * @param receiveId       下一环节接收对象id
     * @param receiveName     下一环节接收对象名称
     * @return
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public StartResult startHwWorkFlow(String inUserId, String inUserName, ReceiveTypeEnum receiveTypeEnum, String receiveId, String receiveName) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        return startWorkFlow(EventFlowConfig.wfIdentifier, inUserId, inUserName, receiveTypeEnum, receiveId, receiveName, 0);
    }

    /**
     * 开启流程
     *
     * @param inUserId   来件用户id
     * @param inUserName 来件用户名称
     * @return
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public StartResult startHwWorkFlow(String inUserId, String inUserName) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        return startWorkFlow(EventFlowConfig.wfIdentifier, inUserId, inUserName, ReceiveTypeEnum.USER, inUserId, inUserName, 0);
    }


    /**
     * 发送到下一环节
     *
     * @param inUserId          来件用户id
     * @param inUserName        来件用户名称
     * @param curActInstId      当前环节实例
     * @param nextActIdentifyId 下一环节标识滴
     * @param content           办理意见
     * @param usedTime          用时
     * @param receiveName       接收对象名称
     * @param receiveId         接收对象id
     * @param receiveTypeEnum   接收对象类型
     * @param limit             时限
     * @param isSpecial         是否是调度
     * @return
     * @throws Exception
     */
    public SingleResult sendToNextActivity(String inUserId, String inUserName, String curActInstId, String nextActIdentifyId, String content, Integer usedTime, String receiveName, String receiveId, ReceiveTypeEnum receiveTypeEnum, Integer limit, boolean isSpecial) throws Exception {
        //region 当前环节
        SendPara sendPara = new SendPara();
        sendPara.setContent(content);
        sendPara.setCurrentInstId(curActInstId);
        sendPara.setDate(LocalDateTime.now());
        sendPara.setUserId(inUserId);
        sendPara.setUserName(inUserName);
        //endregion

        // region 下一环节参数
        SendActivityPara sendActPara = new SendActivityPara();
        sendActPara.setActivityIdentifier(nextActIdentifyId);
        sendActPara.setReceiverType(receiveTypeEnum);
        sendActPara.setReceiverId(receiveId);
        sendActPara.setReceiverName(receiveName);
        sendActPara.setUsedLimit(usedTime == null ? 0 : usedTime);
        sendActPara.setLimit(limit);
        if (limit == null || limit.intValue() == 0) {
            RuntimeActivity runtimeActivity = workflowDefineManager.getRuntimeActivity(EventFlowConfig.wfId, nextActIdentifyId);
            if (ObjectUtils.isNotEmpty(runtimeActivity)) {
                limit = runtimeActivity.getLimit();
            }
        }
        if(limit != null) {
            sendActPara.setLimitValue(limit);
            sendActPara.setShouldFinishedDate(LocalDateTime.now().plusSeconds(limit));
            sendActPara.setLimitStr(Utility.GetTimeString(limit));
        }
        sendActPara.setLimitType(LimitTypeEnum.WorkHour);
        //endregion
        if (isSpecial) {
            return workflowRuntimeManager.specialActivity(sendPara, sendActPara);
        } else {
            return workflowRuntimeManager.sendActivity(sendPara, sendActPara);
        }
    }


    /**
     * 发送到下一环节
     *
     * @param inUserId          来件用户id
     * @param inUserName        来件用户名称
     * @param curActInstId      当前环节实例
     * @param nextActIdentifyId 下一环节标识滴
     * @param content           办理意见
     * @param usedTime          用时
     * @param receiveName       接收对象名称
     * @param receiveId         接收对象id
     * @param receiveTypeEnum   接收对象类型
     * @return
     * @throws Exception
     */
    public SingleResult sendToNextActivity(String inUserId, String inUserName, String curActInstId, String nextActIdentifyId, String content, Integer usedTime, String receiveName, String receiveId, ReceiveTypeEnum receiveTypeEnum) throws Exception {
        return sendToNextActivity(inUserId, inUserName, curActInstId, nextActIdentifyId, content, usedTime, receiveName, receiveId, receiveTypeEnum, 0, false);
    }

    /**
     * 发送到下一环节
     *
     * @param sendActivityPara
     * @return
     */
    public SingleResult sendToNextActivity(SendActPara sendActivityPara) throws Exception {
        return sendToNextActivity(sendActivityPara.getUserId(),
                sendActivityPara.getUserName(),
                sendActivityPara.getCurActInstId(),
                sendActivityPara.getActivityIdentifier(),
                sendActivityPara.getContent(),
                sendActivityPara.getUsedTime(),
                sendActivityPara.getReceiverName(),
                sendActivityPara.getReceiverId(),
                sendActivityPara.getReceiverType(),
                sendActivityPara.getLimit(), false);
    }

    /**
     * 环节调度
     *
     * @param sendActivityPara
     * @return
     * @throws Exception
     */
    public SingleResult specialSendToNextActivity(SendActPara sendActivityPara) throws Exception {
        return sendToNextActivity(sendActivityPara.getUserId(),
                sendActivityPara.getUserName(),
                sendActivityPara.getCurActInstId(),
                sendActivityPara.getActivityIdentifier(),
                sendActivityPara.getContent(),
                sendActivityPara.getUsedTime(),
                sendActivityPara.getReceiverName(),
                sendActivityPara.getReceiverId(),
                sendActivityPara.getReceiverType(),
                sendActivityPara.getLimit(), true);
    }

    /**
     * 流程调度
     *
     * @param rebootFlowPara    重启参数
     * @param sendActSourcePara 目标环节参数
     * @return
     * @throws Exception
     */
    public SingleResult rebootFlowAndDispatcher(RebootFlowPara rebootFlowPara, SendActPara sendActSourcePara) throws Exception {
        SendPara para = new SendPara();
        para.setContent(rebootFlowPara.getRebootReason());
        para.setCurrentInstId(rebootFlowPara.getCurActInstId());
        para.setHandleStatus(HandleEnum.Reboot);
        para.setDate(LocalDateTime.now());
        para.setUserId(rebootFlowPara.getUserId());
        para.setUserName(rebootFlowPara.getUserName());
        // region 下一环节参数
        SendActivityPara sendActTargetPara = new SendActivityPara();
        sendActTargetPara.setActivityIdentifier(sendActSourcePara.getActivityIdentifier().toUpperCase());
        sendActTargetPara.setReceiverType(sendActSourcePara.getReceiverType());
        sendActTargetPara.setReceiverId(sendActSourcePara.getReceiverId());
        sendActTargetPara.setReceiverName(sendActSourcePara.getReceiverName());
        sendActTargetPara.setLimit(sendActSourcePara.getLimit());
        if (sendActSourcePara.getLimit() != null && sendActSourcePara.getLimit().intValue() > 0) {
            sendActTargetPara.setLimitValue(sendActSourcePara.getLimit());
            sendActTargetPara.setShouldFinishedDate(LocalDateTime.now().plusSeconds(sendActSourcePara.getLimit()));
            sendActTargetPara.setLimitStr(Utility.GetTimeString(sendActSourcePara.getLimit()));
        }
        sendActTargetPara.setLimitType(LimitTypeEnum.WorkHour);
        //endregion
        return workflowRuntimeManager.rebootActivity(rebootFlowPara.getWfInstanceId(), para, sendActTargetPara);
    }


    /**
     * 重启流程
     *
     * @param rebootFlowPara 重启参数
     * @return
     * @throws Exception
     */
    public SingleResult rebootFlow(RebootFlowPara rebootFlowPara) throws Exception {
        BackPara para = new BackPara();
        para.setContent(rebootFlowPara.getRebootReason());
        para.setCurrentInstId(rebootFlowPara.getCurActInstId());
        para.setHandleStatus(HandleEnum.Reboot);
        para.setDate(LocalDateTime.now());
        para.setUserId(rebootFlowPara.getUserId());
        para.setUserName(rebootFlowPara.getUserName());
        return workflowRuntimeManager.rebootActivity(para);
    }


    /**
     * 获取环节列表
     *
     * @param workflowId 流程Id
     * @return 环节列表
     * @throws ClassNotFoundException    错误
     * @throws NoSuchMethodException     错误
     * @throws InvocationTargetException 错误
     * @throws InstantiationException    错误
     * @throws IllegalAccessException    错误
     */
    public List<RuntimeActivity> getActivityCollection(String workflowId) throws ClassNotFoundException,
            NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        return workflowDefineManager.getActivityCollection(workflowId);
    }

}
